/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package it.trekker.wifidirect;

import android.content.Context;
import android.net.wifi.WpsInfo;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.ActionListener;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.net.wifi.p2p.WifiP2pManager.ChannelListener;
import android.net.wifi.p2p.WifiP2pManager.PeerListListener;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;

/**
 * A ListFragment that displays available peers on discovery and requests the
 * parent activity to handle user interaction events
 */
public class WiFiDirectPeerListListener implements PeerListListener, ChannelListener {

	private static final String TAG = WiFiDirectPeerListListener.class.getSimpleName();
	
	private List<WifiP2pDevice> peers = new ArrayList<WifiP2pDevice>();
	private WifiP2pDevice device;
	private WifiP2pManager manager;
	private boolean retryChannel = false;
    private Channel channel;
    private Context context;

    
    
    public WiFiDirectPeerListListener(Context context, WifiP2pManager manager, Channel channel) {
    	this.context = context;
    	this.manager = manager;
    	this.channel = channel;
	}

	/**
	 * @return this device
	 */
	public WifiP2pDevice getDevice() {
		return device;
	}

	private static String getDeviceStatus(int deviceStatus) {
		Log.d(TAG, "Peer status :" + deviceStatus);
		
		switch (deviceStatus) {
		case WifiP2pDevice.AVAILABLE:
			return "Available";
		case WifiP2pDevice.INVITED:
			return "Invited";
		case WifiP2pDevice.CONNECTED:
			return "Connected";
		case WifiP2pDevice.FAILED:
			return "Failed";
		case WifiP2pDevice.UNAVAILABLE:
			return "Unavailable";
		default:
			return "Unknown";

		}
	}


	@Override
	public void onPeersAvailable(WifiP2pDeviceList peerList) {
		peers.clear();
		peers.addAll(peerList.getDeviceList());
		if (peers.size() == 0) {
			Log.d(TAG, "No devices found");
			return;
		}

		for(WifiP2pDevice device : peers) {

			// TODO Connect to device

			WifiP2pConfig config = new WifiP2pConfig();
			config.deviceAddress = device.deviceAddress;	// MAC address
			config.wps.setup = WpsInfo.PBC;		// WiFi protected Setup information

			connect(config);
		}

	}

	public void clearPeers() {
		peers.clear();
	}


	public void connect(WifiP2pConfig config) {
		manager.connect(channel, config, new ActionListener() {

			@Override
			public void onSuccess() {
				// WiFiDirectBroadcastReceiver will notify us. Ignore for now.
			}

			@Override
			public void onFailure(int reason) {
			}
		});
	}

	
	public void disconnect() {
		manager.removeGroup(channel, new ActionListener() {

			@Override
			public void onFailure(int reasonCode) {
				Log.d(TAG, "Disconnect failed. Reason :" + reasonCode);

			}

			@Override
			public void onSuccess() {
				Log.d(TAG, "Disconnect succeeded.");
			}

		});
	}
	

	
	@Override
    public void onChannelDisconnected() {
        // we will try once more
        if (manager != null && !retryChannel) {
        	// Channel lost
            resetData();
            retryChannel = true;
            manager.initialize(context, context.getMainLooper(), this);
        } 
        else {
        	// Channel is probably lost premanently
        }
    }
	
	
	/**
     * Remove all peers and clear all fields. This is called on
     * BroadcastReceiver receiving a state change event.
     */
    public void resetData() {
    	clearPeers();
    }

}
